function Category(id, name, parent) {
	this.id = id;
	this.name = name;
	this.parent = parent;
	this.parentId = (parent == null? null: parent.id);

	this.fullName = function() {
		var fullname = this.name;
		if(this.parentId != null) {
			fullname = this.parent.fullName() + ' > ' + fullname;
		}
		return fullname;
	}
}

function CategorySource(categories) {
	this.localdata = categories;
	this.datatype = "array";
	this.datafields = [
		{ name: 'id' },
		{ name: 'name', type: 'string' },
		{ name: 'parentId' }
	];
	this.id = 'id';
}

function CategoryCombo(dropDownDiv, treeDiv, categories, refreshListener) {

	this.value = null;
	this.categories = categories();
	this.timerId = null;
	this.categoriesMap = {};

	this.render = function() {
		this.update();
		var self = this;
		categories.subscribe(function() { self.update(); });
	};

	this.update = function() {
		var self = this;
		this.categories = categories();
		this.categoriesMap = {};
		this.categories.forEach(function(category) {
			self.categoriesMap[category.id] = category;
		}) ;
		var categoriesSource = new CategorySource(this.categories);
		var categoriesAdapter = new $.jqx.dataAdapter(categoriesSource);
		categoriesAdapter.dataBind();
		var records = categoriesAdapter.getRecordsHierarchy('id', 'parentId', 'items', [{ name: 'name', map: 'label' }])
		$(dropDownDiv).jqxDropDownButton({ width: 100, height: 25});
		$(dropDownDiv).jqxDropDownButton('setContent', '<div style="position: relative; margin-left: 3px; margin-top: 5px;">категории</div>');
		$(treeDiv).jqxTree({ source: records, checkboxes: true, hasThreeStates: true });
		$(treeDiv).jqxTree('expandAll');
		$(treeDiv).on('checkChange', function(event) {
			clearTimeout(self.timerId);
			self.timerId = setTimeout(function() { self.updateValue() }, 200);
		});
	};

	this.updateValue = function() {
		var self = this;
		var items = $(treeDiv).jqxTree('getCheckedItems');
		this.value = new Array();
		var itemsMap = {};
		items.forEach(function(item) {
			itemsMap[item.id] = item.id;
		});
		items.forEach(function(item) {
			if(item.parent === null || !(item.parentId in itemsMap)) {
				self.value.push(self.categoriesMap[item.id]);
			}
		});
		refreshListener.refreshCategories(this);
	}
}